local sk__guolun = fk.CreateSkill {

  name = "sk__guolun",

  tags = {},

}



sk__guolun:addEffect(fk.AfterCardsMove, {
  name = "sk__guolun",
  anim_type = "control",
  can_trigger = function(self, event, target, player, data)
    if player:hasSkill(sk__guolun.name) then
      event:setCostData(self, { 0, 0, 0, 0 })
      local n1, n2 = 0, 0
      for _, move in ipairs(data) do
        if move.moveReason == fk.ReasonDraw and move.toArea == Card.PlayerHand then
          if move.to == player or player:getMark("@sk__guolun") == "status3" or player:getMark("@sk__guolun") == "status4" then
            n1 = n1 + #move.moveInfo
          end
        end
        if move.moveReason == fk.ReasonDiscard then
          if move.from == player or player:getMark("@sk__guolun") == "status3" or player:getMark("@sk__guolun") == "status4" then
            for _, info in ipairs(move.moveInfo) do
              if info.fromArea == Card.PlayerHand or info.fromArea == Card.PlayerEquip then
                n2 = n2 + 1
              end
            end
          end
        end
      end
      event:setCostData(self, { n1, n2, event:getCostData(self)[3], event:getCostData(self)[4] })
      if #player.room.alive_players > 0 then
        if player:getMark("sk__guolun1-turn") == 0 then
          if event:getCostData(self)[2] > 0 or event:getCostData(self)[3] > 0 then
            return true
          elseif event:getCostData(self)[1] > 0 then
            if table.find(player.room:getOtherPlayers(player), function(p)
                  return not p:isNude()
                end) then
              return true
            end
          elseif event:getCostData(self)[4] > 0 then
            if table.find(player.room:getOtherPlayers(player), function(p)
                  return p:isWounded()
                end) then
              return true
            end
          end
        end
        if player:getMark("@sk__guolun") ~= 0 and player:getMark("sk__guolun2-turn") == 0 then
          if event:getCostData(self)[1] > 0 or event:getCostData(self)[4] > 0 then
            return true
          elseif event:getCostData(self)[2] > 0 then
            if table.find(player.room:getOtherPlayers(player), function(p)
                  return not p:isNude()
                end) then
              return true
            end
          elseif event:getCostData(self)[3] > 0 then
            if table.find(player.room:getOtherPlayers(player), function(p)
                  return p:isWounded()
                end) then
              return true
            end
          end
        end
      end
    end
  end,
  on_trigger = function(self, event, target, player, data)
    for _, move in ipairs(data) do
      if not player:hasSkill(sk__guolun.name) or
          (player:getMark("@sk__guolun") == 0 and player:getMark("sk__guolun1-turn") > 0) or
          (player:getMark("@sk__guolun") ~= 0 and player:getMark("sk__guolun1-turn") > 0 and player:getMark("sk__guolun2-turn") > 0)
      then
        return
      end
      local n1, n2 = 0, 0
      if move.moveReason == fk.ReasonDraw and move.toArea == Card.PlayerHand then
        if move.to == player or player:getMark("@sk__guolun") == "status3" or player:getMark("@sk__guolun") == "status4" then
          n1 = n1 + #move.moveInfo
        end
      end
      if move.moveReason == fk.ReasonDiscard then
        if move.from == player or player:getMark("@sk__guolun") == "status3" or player:getMark("@sk__guolun") == "status4" then
          for _, info in ipairs(move.moveInfo) do
            if info.fromArea == Card.PlayerHand or info.fromArea == Card.PlayerEquip then
              n2 = n2 + 1
            end
          end
        end
      end
      if n1 > 0 then
        if (player:getMark("sk__guolun1-turn") == 0 and table.find(player.room:getOtherPlayers(player), function(p)
              return not p:isNude()
            end)) or
            (player:getMark("@sk__guolun") ~= 0 and player:getMark("sk__guolun2-turn") == 0) then
          self:doCost(event, target, player, { 1, n1 })
        end
      end
      if n2 > 0 then
        if player:getMark("sk__guolun1-turn") == 0 or
            (player:getMark("@sk__guolun") ~= 0 and player:getMark("sk__guolun2-turn") == 0 and
              table.find(player.room:getOtherPlayers(player), function(p)
                return not p:isNude()
              end)) then
          self:doCost(event, target, player, { 2, n2 })
        end
      end
    end
  end,
  on_cost = function(self, event, target, player, data)
    local room = player.room
    local prompt
    if player:getMark("@sk__guolun") == 0 then
      if data[1] == 1 then
        prompt = 2
      else
        prompt = 1
      end
    else
      local choices, all_choices = {}, {}
      if data[1] == 1 or data[1] == 3 then
        table.insert(all_choices, "sk__guolun_" .. (data[1] + 1) .. ":::" .. data[2])
        if player:getMark("sk__guolun1-turn") == 0 then
          table.insert(choices, "sk__guolun_" .. (data[1] + 1) .. ":::" .. data[2])
        end
      else
        table.insert(all_choices, "sk__guolun_" .. (data[1] - 1) .. ":::" .. data[2])
        if player:getMark("sk__guolun1-turn") == 0 then
          table.insert(choices, "sk__guolun_" .. (data[1] - 1) .. ":::" .. data[2])
        end
      end
      if player:getMark("@sk__guolun") ~= 0 then
        table.insert(all_choices, "sk__guolun_" .. data[1] .. ":::" .. data[2])
        if player:getMark("sk__guolun2-turn") == 0 then
          table.insert(choices, "sk__guolun_" .. data[1] .. ":::" .. data[2])
        end
      end
      local choice
      if #choices == 1 then
        choice = choices[1]
      else
        table.insert(all_choices, "Cancel")
        table.insert(choices, "Cancel")
        choice = room:askForChoice(player, choices, sk__guolun.name, nil, false, all_choices)
        if choice == "Cancel" then return end
      end
      prompt = tonumber(choice[12])
    end
    local targets = table.map(room:getOtherPlayers(player), Util.IdMapper)
    if prompt == 2 then
      targets = table.map(table.filter(room:getOtherPlayers(player), function(p)
        return not p:isNude()
      end), Util.IdMapper)
    elseif prompt == 3 then
      targets = table.map(table.filter(room:getOtherPlayers(player), function(p)
        return p:isWounded()
      end), Util.IdMapper)
    end
    local to = room:askForChoosePlayers(player, targets, 1, 1,
      "#sk__guolun" .. prompt .. "-choose:::" .. data[2], sk__guolun.name, true, false)
    if #to > 0 then
      event:setCostData(self, { to[1], prompt, data[2] })
      if prompt ~= data[1] then
        room:setPlayerMark(player, "sk__guolun1-turn", 1)
      else
        room:setPlayerMark(player, "sk__guolun2-turn", 1)
      end
      return true
    end
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    local to = room:getPlayerById(event:getCostData(self)[1])
    local n = event:getCostData(self)[3]
    if event:getCostData(self)[2] == 1 then
      to:drawCards(n, sk__guolun.name)
    elseif event:getCostData(self)[2] == 2 then
      room:askForDiscard(to, n, n, true, sk__guolun.name, false)
    elseif event:getCostData(self)[2] == 3 then
      room:recover({
        who = to,
        num = math.min(n, to:getLostHp()),
        recoverBy = player,
        skillName = sk__guolun.name,
      })
    elseif event:getCostData(self)[2] == 4 then
      room:damage {
        from = player,
        to = to,
        damage = n,
        skillName = sk__guolun.name,
      }
    end
  end,
})
sk__guolun:addEffect(fk.HpRecover, {
  name = "sk__guolun",
  anim_type = "control",
  can_trigger = function(self, event, target, player, data)
    if player:hasSkill(sk__guolun.name) then
      event:setCostData(self, { 0, 0, 0, 0 })
      if player:getMark("@sk__guolun") == "status4" then
        if event == fk.HpRecover then
           event:setCostData(self, { 0, 0, data.num, 0 })
        elseif event == fk.Damage and target then
          event:setCostData(self, { 0, 0, 0, data.damage }) 
        end
      end
      if #player.room.alive_players > 0 then
        if player:getMark("sk__guolun1-turn") == 0 then
          if event:getCostData(self)[2] > 0 or event:getCostData(self)[3] > 0 then
            return true
          elseif event:getCostData(self)[1] > 0 then
            if table.find(player.room:getOtherPlayers(player), function(p)
                  return not p:isNude()
                end) then
              return true
            end
          elseif event:getCostData(self)[4] > 0 then
            if table.find(player.room:getOtherPlayers(player), function(p)
                  return p:isWounded()
                end) then
              return true
            end
          end
        end
        if player:getMark("@sk__guolun") ~= 0 and player:getMark("sk__guolun2-turn") == 0 then
          if event:getCostData(self)[1] > 0 or event:getCostData(self)[4] > 0 then
            return true
          elseif event:getCostData(self)[2] > 0 then
            if table.find(player.room:getOtherPlayers(player), function(p)
                  return not p:isNude()
                end) then
              return true
            end
          elseif event:getCostData(self)[3] > 0 then
            if table.find(player.room:getOtherPlayers(player), function(p)
                  return p:isWounded()
                end) then
              return true
            end
          end
        end
      end
    end
  end,
  on_trigger = function(self, event, target, player, data)
    if player:getMark("sk__guolun1-turn") == 0 or
        (player:getMark("@sk__guolun") ~= 0 and player:getMark("sk__guolun2-turn") == 0 and
          table.find(player.room:getOtherPlayers(player), function(p)
            return p:isWounded()
          end)) then
      self:doCost(event, target, player, { 3, data.num })
    end
  end,
  on_cost = function(self, event, target, player, data)
    local room = player.room
    local prompt
    if player:getMark("@sk__guolun") == 0 then
      if data[1] == 1 then
        prompt = 2
      else
        prompt = 1
      end
    else
      local choices, all_choices = {}, {}
      if data[1] == 1 or data[1] == 3 then
        table.insert(all_choices, "sk__guolun_" .. (data[1] + 1) .. ":::" .. data[2])
        if player:getMark("sk__guolun1-turn") == 0 then
          table.insert(choices, "sk__guolun_" .. (data[1] + 1) .. ":::" .. data[2])
        end
      else
        table.insert(all_choices, "sk__guolun_" .. (data[1] - 1) .. ":::" .. data[2])
        if player:getMark("sk__guolun1-turn") == 0 then
          table.insert(choices, "sk__guolun_" .. (data[1] - 1) .. ":::" .. data[2])
        end
      end
      if player:getMark("@sk__guolun") ~= 0 then
        table.insert(all_choices, "sk__guolun_" .. data[1] .. ":::" .. data[2])
        if player:getMark("sk__guolun2-turn") == 0 then
          table.insert(choices, "sk__guolun_" .. data[1] .. ":::" .. data[2])
        end
      end
      local choice
      if #choices == 1 then
        choice = choices[1]
      else
        table.insert(all_choices, "Cancel")
        table.insert(choices, "Cancel")
        choice = room:askForChoice(player, choices, sk__guolun.name, nil, false, all_choices)
        if choice == "Cancel" then return end
      end
      prompt = tonumber(choice[12])
    end
    local targets = table.map(room:getOtherPlayers(player), Util.IdMapper)
    if prompt == 2 then
      targets = table.map(table.filter(room:getOtherPlayers(player), function(p)
        return not p:isNude()
      end), Util.IdMapper)
    elseif prompt == 3 then
      targets = table.map(table.filter(room:getOtherPlayers(player), function(p)
        return p:isWounded()
      end), Util.IdMapper)
    end
    local to = room:askForChoosePlayers(player, targets, 1, 1,
      "#sk__guolun" .. prompt .. "-choose:::" .. data[2], sk__guolun.name, true, false)
    if #to > 0 then
      event:setCostData(self, { to[1], prompt, data[2] })
      if prompt ~= data[1] then
        room:setPlayerMark(player, "sk__guolun1-turn", 1)
      else
        room:setPlayerMark(player, "sk__guolun2-turn", 1)
      end
      return true
    end
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    local to = room:getPlayerById(event:getCostData(self)[1])
    local n = event:getCostData(self)[3]
    if event:getCostData(self)[2] == 1 then
      to:drawCards(n, sk__guolun.name)
    elseif event:getCostData(self)[2] == 2 then
      room:askForDiscard(to, n, n, true, sk__guolun.name, false)
    elseif event:getCostData(self)[2] == 3 then
      room:recover({
        who = to,
        num = math.min(n, to:getLostHp()),
        recoverBy = player,
        skillName = sk__guolun.name,
      })
    elseif event:getCostData(self)[2] == 4 then
      room:damage {
        from = player,
        to = to,
        damage = n,
        skillName = sk__guolun.name,
      }
    end
  end,
})
sk__guolun:addEffect(fk.Damage, {
  name = "sk__guolun",
  anim_type = "control",
  can_trigger = function(self, event, target, player, data)
    if player:hasSkill(sk__guolun.name) then
      event:setCostData(self, { 0, 0, 0, 0 })
      if player:getMark("@sk__guolun") == "status4" then
        if target then
          event:setCostData(self, { 0, 0, 0, data.damage })
        end
      end
      if #player.room.alive_players > 0 then
        if player:getMark("sk__guolun1-turn") == 0 then
          if event:getCostData(self)[2] > 0 or event:getCostData(self)[3] > 0 then
            return true
          elseif event:getCostData(self)[1] > 0 then
            if table.find(player.room:getOtherPlayers(player), function(p)
                  return not p:isNude()
                end) then
              return true
            end
          elseif event:getCostData(self)[4] > 0 then
            if table.find(player.room:getOtherPlayers(player), function(p)
                  return p:isWounded()
                end) then
              return true
            end
          end
        end
        if player:getMark("@sk__guolun") ~= 0 and player:getMark("sk__guolun2-turn") == 0 then
          if event:getCostData(self)[1] > 0 or event:getCostData(self)[4] > 0 then
            return true
          elseif event:getCostData(self)[2] > 0 then
            if table.find(player.room:getOtherPlayers(player), function(p)
                  return not p:isNude()
                end) then
              return true
            end
          elseif event:getCostData(self)[3] > 0 then
            if table.find(player.room:getOtherPlayers(player), function(p)
                  return p:isWounded()
                end) then
              return true
            end
          end
        end
      end
    end
  end,
  on_trigger = function(self, event, target, player, data)
    if (player:getMark("sk__guolun1-turn") == 0 and table.find(player.room:getOtherPlayers(player), function(p)
          return p:isWounded()
        end)) or
        (player:getMark("@sk__guolun") ~= 0 and player:getMark("sk__guolun2-turn") == 0) then
      self:doCost(event, target, player, { 4, data.damage })
    end
  end,
  on_cost = function(self, event, target, player, data)
    local room = player.room
    local prompt
    if player:getMark("@sk__guolun") == 0 then
      if data[1] == 1 then
        prompt = 2
      else
        prompt = 1
      end
    else
      local choices, all_choices = {}, {}
      if data[1] == 1 or data[1] == 3 then
        table.insert(all_choices, "sk__guolun_" .. (data[1] + 1) .. ":::" .. data[2])
        if player:getMark("sk__guolun1-turn") == 0 then
          table.insert(choices, "sk__guolun_" .. (data[1] + 1) .. ":::" .. data[2])
        end
      else
        table.insert(all_choices, "sk__guolun_" .. (data[1] - 1) .. ":::" .. data[2])
        if player:getMark("sk__guolun1-turn") == 0 then
          table.insert(choices, "sk__guolun_" .. (data[1] - 1) .. ":::" .. data[2])
        end
      end
      if player:getMark("@sk__guolun") ~= 0 then
        table.insert(all_choices, "sk__guolun_" .. data[1] .. ":::" .. data[2])
        if player:getMark("sk__guolun2-turn") == 0 then
          table.insert(choices, "sk__guolun_" .. data[1] .. ":::" .. data[2])
        end
      end
      local choice
      if #choices == 1 then
        choice = choices[1]
      else
        table.insert(all_choices, "Cancel")
        table.insert(choices, "Cancel")
        choice = room:askForChoice(player, choices, sk__guolun.name, nil, false, all_choices)
        if choice == "Cancel" then return end
      end
      prompt = tonumber(choice[12])
    end
    local targets = table.map(room:getOtherPlayers(player), Util.IdMapper)
    if prompt == 2 then
      targets = table.map(table.filter(room:getOtherPlayers(player), function(p)
        return not p:isNude()
      end), Util.IdMapper)
    elseif prompt == 3 then
      targets = table.map(table.filter(room:getOtherPlayers(player), function(p)
        return p:isWounded()
      end), Util.IdMapper)
    end
    local to = room:askForChoosePlayers(player, targets, 1, 1,
      "#sk__guolun" .. prompt .. "-choose:::" .. data[2], sk__guolun.name, true, false)
    if #to > 0 then
      event:setCostData(self, { to[1], prompt, data[2] })
      if prompt ~= data[1] then
        room:setPlayerMark(player, "sk__guolun1-turn", 1)
      else
        room:setPlayerMark(player, "sk__guolun2-turn", 1)
      end
      return true
    end
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    local to = room:getPlayerById(event:getCostData(self)[1])
    local n = event:getCostData(self)[3]
    if event:getCostData(self)[2] == 1 then
      to:drawCards(n, sk__guolun.name)
    elseif event:getCostData(self)[2] == 2 then
      room:askForDiscard(to, n, n, true, sk__guolun.name, false)
    elseif event:getCostData(self)[2] == 3 then
      room:recover({
        who = to,
        num = math.min(n, to:getLostHp()),
        recoverBy = player,
        skillName = sk__guolun.name,
      })
    elseif event:getCostData(self)[2] == 4 then
      room:damage {
        from = player,
        to = to,
        damage = n,
        skillName = sk__guolun.name,
      }
    end
  end,
})

return sk__guolun
